﻿using FEM.Result;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PBSD_Development
{
    /// <summary>
    /// 楼层对象
    /// </summary>
    public class StoreyObj
    {
        /// <summary>
        /// 楼层
        /// </summary>
        private Storey storey { set; get; }

        /// <summary>
        /// 弹塑性分析结果
        /// </summary>
        private FEMResult result { set; get; }

        /// <summary>
        /// 楼层绑定塔楼信息
        /// </summary>
        public TowerObj Tower { set; get; }

        /// <summary>
        /// 塔楼序号
        /// </summary>
        public int TowerIndex
        {
            get
            {
                return this.storey.TowerIndex;
            }
        }

        /// <summary>
        /// 楼层序号
        /// </summary>
        public int StoreyIndex
        {
            get
            {
                return this.storey.StoreyIndex;
            }
        }

        /// <summary>
        /// 获得层间位移角对象
        /// </summary>
        /// <param name="isX"></param>
        /// <returns></returns>
        private List<Drift> getDrifts(bool isX)
        {
            return this.result.GlobalResult.Drifts.GetDrifts(this.storey, isX);
        }

        /// <summary>
        /// 获得层间位移角对象
        /// </summary>
        /// <returns></returns>
        private List<Drift> getDrifts()
        {
            //层间位移角
            var dirctList = this.getDrifts(true);
            dirctList.AddRange(this.getDrifts(false));
            return dirctList;
        }

        /// <summary>
        /// 获得楼层切割面
        /// </summary>
        /// <returns></returns>
        private List<StructSection> getSections()
        {
            return this.result.GlobalResult.Sections.GetSections(this.storey);
        }

        /// <summary>
        /// 获得楼层内的单元
        /// </summary>
        /// <param name="storey"></param>
        /// <returns></returns>
        public List<ElementObj> GetElementList(ElementGroupObj groupObj)
        {
            return groupObj.GetElementList(this);
        }

        /// <summary>
        /// 楼层平均变形
        /// </summary>
        /// <param name="storey"></param>
        /// <returns></returns>
        public float GetAVGDeform(LoadCaseObj loadcase, ElementGroupObj groupObj)
        {
            return groupObj.GetAVGDeform(loadcase, this);
        }

        /// <summary>
        /// 楼层平均能力需求比
        /// </summary>
        /// <param name="loadcase"></param>
        /// <param name="storey"></param>
        /// <param name="deformType"></param>
        /// <returns></returns>
        public float GetAVGDeformDCR(LoadCaseObj loadcase, ElementGroupObj groupObj, DeformType deformType)
        {
            return groupObj.GetAVGDeformDCR(loadcase, this, deformType);
        }

        /// <summary>
        /// 楼层内单元组构件的平均能力需求比
        /// </summary>
        /// <param name="loadcase"> 工况 </param>
        /// <param name="storey"> 楼层 </param>
        /// <param name="deformType"> 性能类型 </param>
        /// <returns> 需求能力比 </returns>
        public float GetMaxDeformDCR(LoadCaseObj loadcase, ElementGroupObj groupObj, DeformType deformType)
        {
            return groupObj.GetMaxDeformDCR(loadcase, this, deformType);
        }

        /// <summary>
        /// 特定楼层的构件性能状态占比
        /// </summary>
        /// <param name="loadcase"></param>
        /// <param name="storey"></param>
        /// <returns></returns>
        public List<double> GetDeformPerformRatio(LoadCaseObj loadcase, ElementGroupObj groupObj)
        {
            //获得对应楼层的性能状态占比
            return groupObj.GetStoreyDeformPerformRatio(loadcase, this);
        }

        /// <summary>
        /// 是否相同楼层
        /// </summary>
        /// <param name="towerIndex"></param>
        /// <param name="storeyIndex"></param>
        /// <returns></returns>
        public bool isSameStorey(int towerIndex, int storeyIndex)
        {
            return this.storey.isSameStorey(towerIndex, storeyIndex);
        }

        /// <summary>
        /// 楼层最大层间位移角的对象
        /// </summary>
        /// <param name="loadCase"></param>
        /// <param name="isX"></param>
        /// <returns></returns>
        private bool GetMaxDrift(LoadCaseObj loadCase, bool isX, out Drift drift)
        {
            //层间位移角初始化
            drift = new Drift();
            //获得对象
            var drifts = this.getDrifts(isX);
            //层间位移角存在
            if (drifts.Count == 0) return false;
            //获得最大层间位移角对象
            drift = drifts.Aggregate((dr1, dr2) => 
            Math.Abs(dr1[loadCase.Name]) > Math.Abs(dr2[loadCase.Name]) ? dr1 : dr2);
            //最大层间位移角存在
            return true;
        }

        /// <summary>
        /// 楼层最大层间位移角的对象
        /// </summary>
        /// <param name="loadCase"></param>
        /// <param name="isX"></param>
        /// <returns></returns>
        private bool GetMaxDrift(LoadCaseObj loadCase, out Drift drift)
        {
            //层间位移角初始化
            drift = new Drift();
            //获得对象
            var drifts = this.getDrifts();
            //层间位移角存在
            if (drifts.Count == 0) return false;
            //获得最大层间位移角对象
            drift = drifts.Aggregate((dr1, dr2) =>
            Math.Abs(dr1[loadCase.Name]) > Math.Abs(dr2[loadCase.Name]) ? dr1 : dr2);
            //最大层间位移角存在
            return true;
        }

        /// <summary>
        /// 楼层最大响应的对象
        /// </summary>
        /// <param name="loadCase"></param>
        /// <param name="isX"></param>
        /// <returns></returns>
        private bool GetMaxDrift(LoadCaseObj loadCase, GlobalResultType resultType, bool isX, out Drift drift)
        {
            //层间位移角初始化
            drift = new Drift();
            //获得对象
            var drifts = this.getDrifts(isX);
            //层间位移角存在
            if (drifts.Count == 0) return false;
            //获得最大层间位移角对象
            drift = drifts.Aggregate((dr1, dr2) => dr1[resultType, loadCase.Name].GetAbsMax(false) > dr2[resultType, loadCase.Name].GetAbsMax(false) ? dr1 : dr2);
            //最大层间位移角存在
            return true;
        }

        /// <summary>
        /// 楼层最大响应的对象
        /// </summary>
        /// <param name="loadCase"></param>
        /// <param name="isX"></param>
        /// <returns></returns>
        private bool GetMaxDrift(LoadCaseObj loadCase, GlobalResultType resultType, out Drift drift)
        {
            //层间位移角初始化
            drift = new Drift();
            //获得对象
            var drifts = this.getDrifts();
            //层间位移角存在
            if (drifts.Count == 0) return false;
            //获得最大层间位移角对象
            drift = drifts.Aggregate((dr1, dr2) => dr1[resultType, loadCase.Name].GetAbsMax(false) > dr2[resultType, loadCase.Name].GetAbsMax(false) ? dr1 : dr2);
            //最大层间位移角存在
            return true;
        }

        /// <summary>
        /// 楼层最大响应的对象
        /// </summary>
        /// <param name="loadCase"></param>
        /// <param name="isX"></param>
        /// <returns></returns>
        private double GetMaxResponse(LoadCaseObj loadCase, GlobalResultType resultType, bool isX)
        {
            //获得最大层间位移角对象
            Drift drift;
            if (!this.GetMaxDrift(loadCase, resultType, isX, out drift)) return 0;
            else return drift[resultType, loadCase.Name].GetAbsMax(false);
        }

        /// <summary>
        /// 楼层最大响应的对象
        /// </summary>
        /// <param name="loadCase"></param>
        /// <param name="isX"></param>
        /// <returns></returns>
        private double GetMaxResponse(LoadCaseObj loadCase, GlobalResultType resultType)
        {
            //获得最大层间位移角对象
            Drift drift;
            if (!this.GetMaxDrift(loadCase, resultType, out drift)) return 0;
            else return drift[resultType, loadCase.Name].GetAbsMax(false);
        }

        /// <summary>
        /// 获得楼层响应
        /// </summary>
        /// <param name="loadCase"></param>
        /// <param name="reaction"></param>
        /// <returns></returns>
        public double GetMaxReaction(LoadCaseObj loadCase, StoreyReaction reaction)
        {
            //响应对象
            Drift drift;
            //枚举响应
            switch (reaction)
            {
                case StoreyReaction.Drift:
                    if (!this.GetMaxDrift(loadCase, out drift)) return 0;
                    else return Math.Abs(drift[loadCase.Name]);

                case StoreyReaction.ResDrift:
                    //获得对象
                    var drifts = this.getDrifts();
                    //层间位移角存在
                    if (drifts.Count == 0) return 0;
                    //返回最大值
                    return (from subDrift in drifts select Math.Abs(subDrift.ResDriftDict[loadCase.Name])).ToList().Max();

                case StoreyReaction.Accel:
                    return this.GetMaxResponse(loadCase, GlobalResultType.Accel);

                case StoreyReaction.Disp:
                    return this.GetMaxResponse(loadCase, GlobalResultType.Disp);

                default:
                    return 0;
            }
        }

        /// <summary>
        /// 获得楼层响应
        /// </summary>
        /// <param name="loadCase"></param>
        /// <param name="reaction"></param>
        /// <returns></returns>
        public double GetMaxReaction(LoadCaseObj loadCase, StoreyReaction reaction, bool isX)
        {
            //响应对象
            Drift drift;
            //枚举响应
            switch (reaction)
            {
                case StoreyReaction.Drift:
                    if (!this.GetMaxDrift(loadCase, isX, out drift)) return 0;
                    else return Math.Abs(drift[loadCase.Name]);

                case StoreyReaction.ResDrift:
                    //获得对象
                    var drifts = this.getDrifts(isX);
                    //层间位移角存在
                    if (drifts.Count == 0) return 0;
                    //返回最大值
                    return (from subDrift in drifts select Math.Abs(subDrift.ResDriftDict[loadCase.Name])).ToList().Max();

                case StoreyReaction.Accel:
                    return this.GetMaxResponse(loadCase, GlobalResultType.Accel, isX);

                case StoreyReaction.Disp:
                    return this.GetMaxResponse(loadCase, GlobalResultType.Disp, isX);

                default:
                    return 0;
            }
        }

        /// <summary>
        /// 最大楼层剪力
        /// </summary>
        /// <param name="loadCase"> 工况 </param>
        /// <param name="isX"> X向/Y向剪力 </param>
        /// <returns> 剪力 </returns>
        public double GetMaxForce(LoadCaseObj loadCase, bool isX)
        {
            //获得楼层切割面
            var sectios = this.getSections();
            //层间位移角存在
            if (sectios.Count == 0) return 0;
            //方向
            var sectionForceType = isX ? StructSectionType.H1Force : StructSectionType.H2Force;
            //返回最大值
            return (from section in sectios select Math.Abs(section[loadCase.Name, sectionForceType])).ToList().Max();
        }

        /// <summary>
        /// 最大楼层倾覆弯矩
        /// </summary>
        /// <param name="loadCase"> 工况 </param>
        /// <param name="isX"> X向/Y向倾覆弯矩 </param>
        /// <returns> 倾覆弯矩 </returns>
        public double GetMaxMoment(LoadCaseObj loadCase, bool isX)
        {
            //获得楼层切割面
            var sectios = this.getSections();
            //层间位移角存在
            if (sectios.Count == 0) return 0;
            //方向
            var sectionForceType = isX ? StructSectionType.H2Moment : StructSectionType.H1Moment;
            //返回最大值
            return (from section in sectios select Math.Abs(section[loadCase.Name, sectionForceType])).ToList().Max();
        }

        /// <summary>
        /// 空的构造函数
        /// </summary>
        public StoreyObj()
        {

        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="storey"></param>
        /// <param name="result"></param>
        public StoreyObj(TowerObj tower, Storey storey, FEMResult result)
        {
            this.Tower = tower;
            this.storey = storey;
            this.result = result;
        }

    }
}
